home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga CD-ROM Collection
/
Amiga CD-ROM Collection - Auge 4000 and Cactus and Demo Util.iso
/
auge4000
/
18
/
virusx
/
virusx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-19
|
13KB
|
491 lines
/* VirusX - by Steve Tibbett
The complete Virus Elimination System!
Please - if you find a new virus, Send me a copy!
(And warn me it's on the disk!). I want to keep
this program current. (Feel free to put something
neat (but not copyrighted) on the disk also!
*/
/* - Ok, it's not the cleanest code in the world - it was written in two
days, for a specific purpose, and it works! */
struct Port *diskport; /* disk's port.*/
struct IOStdReq *diskreq; /* disk's IOStdReq */
int DisksChecked, DisksInstalled, SCAFound; /* for title bar info */
char titlebuffer[80];
/* Who needs includes with Aztec? Everything's precompiled! */
/* Amount of boot code we've got (approx): */
#define BSIZE 40
int ChangeCount[4]; /* TD_CHANGECOUNT for all 4 drives */
int LastSum; /* Used in the checksumming */
int CheckDrives; /* Boolean, from the command line */
int error; /* sort of a temporary variable sort of */
unsigned char diskbuffer[3*512];/* Everything ends up in here.
I suppose I should have AllocMem'ed this,
but it's SO easy this way */
/* Warning messages. These messages get modified before being displayed
(Unless you DO have a DF9:) */
char TEXTPTR[] = "Danger: The disk in DF9: is";
char NBCTEXT[] = "Danger: The disk in DF9: has";
/* This is a byte by byte copy of working boot block code. Check it
out if you like. This is what gets written back to the disk when you
ask VirusX to fix a disk. */
unsigned char bootblock[] = { 'D', 'O', 'S', 0, 0xc0, 0x20, 0x0f, 0x19,
0, 0, 3, 0x70, 0x43, 0xfa, 0, 0x18,
0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64,
0x6f, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,0,0,0,0,0};
/* for IntuiText's */
char def_font[] ="topaz.font";
struct TextAttr TxtAt_Plain = { (UBYTE *)def_font, 8,
FS_NORMAL, FPF_ROMFONT};
/*** Non SCA warning requester IntuiText's ***/
struct IntuiText Body2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *)"Nonstandard Boot Code!", NULL };
struct IntuiText Body1 = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2 };
struct IntuiText Pos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL };
struct IntuiText Neg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL };
/***** SCA Danger Requester IntuiText's ******/
struct IntuiText SCABody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with an SCA Virus!!", NULL };
struct IntuiText SCABody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)TEXTPTR, &SCABody2 };
struct IntuiText SCAPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL };
struct IntuiText SCANeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL };
/***** Write Protect Error Requester IntuiText's ******/
struct IntuiText ERRBody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL };
struct IntuiText ERRBody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)"DISK ERROR: Disk is", &ERRBody2 };
struct IntuiText ERRPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL };
struct IntuiText ERRNeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL };
/***** Rewrite block? Really? ******/
struct IntuiText REWBody3 = {
0, 1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL };
struct IntuiText REWBody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3};
struct IntuiText REWBody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)"Are you sure you want to", &REWBody2 };
struct IntuiText REWPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL };
struct IntuiText REWNeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL };
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Window *LittleWindow;
struct IntuiMessage *Message;
struct RastPort *RP;
int Keepgoing; /* a boolean flag. it's false when we want out. */
int Class, Code; /* for storing IntuiNewspaper things. */
int x, y, i; /* left over from my using Basic */
/*** The Newwindow Structure. ***/
char TITLETEXT[] = "VirusX 1.0 by Steve Tibbett";
struct NewWindow NewLittleWindow = {
128, /* Left, Top, Width, Height */
0,
300,
10,
0, /* Frontpen, Backpen */
1,
DISKINSERTED | CLOSEWINDOW | VANILLAKEY | MOUSEBUTTONS, /* IDCMP Flagz */
WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
NULL,
NULL,
TITLETEXT, /* My name. Dont touch it!! */
NULL,
NULL,
0,
0,
0,
0,
WBENCHSCREEN,
};
/*********************Da Beginnin*************************/
main(argc, argv)
int argc;
char *argv[];
{
int OldPri;
/* Come on, folks, is intuition never NOT going to be available???? */
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
/* If checkdrives is true, later on it means we want to check all the drives
with disks in them for viruses. */
CheckDrives = FALSE;
if (argc == 0) /* If argc == 0, we're a Workbench deryvatuv */
{
CheckDrives = TRUE; /* If we're workbench, we want to check drives */
}
else
{
for (i = 0; i < argc; i++)
{
if (argv[i][0] == '-') /* if we find a -C, we want CheckDrives */
{
if (argv[i][1] == 'c' | argv[i][1] == 'C') CheckDrives = TRUE;
};
if (argv[i][0] == '?') /* HELP ME! */
{
puts("Usage: VirusX [-C]\n");
puts(" -c checks all drives for Virus upon execution\n");
exit(FALSE);
};
};
};
/* Save OldPri so we can restore it later on. We're so nice. */
OldPri = SetTaskPri(FindTask(0), 19); /* and stick us up high. */
diskport = CreatePort(0,0);
diskreq = CreateStdIO(diskport);
SetUp();
DoLittle(); /* The main loop. Do Little. Ya. */
/* restore priorities to saneness, and take off, eh? */
SetTaskPri(FindTask(0), OldPri);
DeletePort(diskport);
DeleteStdIO(diskreq);
exit(FALSE);
}
/*********************/
DoLittle()
{
register int Code;
register int Class; /* gee */
register int KG2; /* KeepGoing 2. Another booleean. */
LittleWindow = OpenWindow(&NewLittleWindow);
if (LittleWindow == NULL) exit(400L); /* No memory to open little window! */
KG2 = TRUE;
RP = LittleWindow->RPort; /* easier than typing Move(LittleWindow->RP... all
the time */
if (CheckDrives == TRUE) /* We'll fake it: Set changecount to 1000, to*/
{ /*make people think it's been changed */
for (x = 0; x < 4; x++) ChangeCount[x] = 1000;
CheckBlock(); /* CheckBlock() checks boot block for virus. */
CheckDrives = FALSE; /* so we don't do it again */
};
SetAPen(RP, 1);
SetBPen(RP, 0);
SetDrMd(RP, JAM2); /* ya. JAM 2! Love that name! */
while (KG2 == TRUE)
{
sprintf(titlebuffer, "VirusX: Disks Checked: %d Disks Installed: %d Viruses Found: %d", DisksChecked, DisksInstalled, SCAFound);
SetWindowTitles(LittleWindow, -1, titlebuffer);
Message = GetMsg(LittleWindow->UserPort);
while (Message == NULL)
{
/* Lets be nice to other tasks! Ya! */
Wait(1<<LittleWindow->UserPort->mp_SigBit);
Message = GetMsg(LittleWindow->UserPort);
};
Class = Message->Class;
Code = Message->Code;
if (Message != NULL) ReplyMsg(Message);
if (Class == CLOSEWINDOW)
{
CloseWindow(LittleWindow);
exit(FALSE);
};
if (Class == DISKINSERTED) CheckBlock();
};
/* KG2 = false, we fell thru to here. Ow. */
CloseWindow(LittleWindow);
return;
}
/**********************/
puts(str) /* outputs a string, but is REAL small. */
char *str[];
{
Write(Output(), str, strlen(str));
}
/********************/
/* Opens trackdisk, finds out who's out there, and sets Changecount up accordioningly. */
/********************/
SetUp()
{
for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
{
ChangeCount[x] = 0;
error = OpenDevice("trackdisk.device",x,diskreq,0);
if (error > 0) continue; /* no drive here */
diskreq->io_Command = TD_CHANGENUM;
error = DoIO(diskreq);
ChangeCount[x] = diskreq->io_Actual; /* save changecount for later */
CloseDevice(diskreq);
};
}
/********************************/
/* This routine returns which drive changed disks lately */
/********************************/
WhoChanged()
{
int RetVal; /* The value we'll return */
RetVal = -1; /* return -1 if all else fails */
for (x = 0; x < 4; x++)
{
if (ChangeCount[x] == 0) continue; /* no drive here */
error = OpenDevice("trackdisk.device",x,diskreq,0);
if (error > 0) continue; /* no drive here */
diskreq->io_Command = TD_CHANGESTATE;
DoIO(diskreq);
if (diskreq->io_Actual != 0)
{
continue;
};
diskreq->io_Command = TD_CHANGENUM;
DoIO(diskreq);
if (diskreq->io_Actual != ChangeCount[x])
{
RetVal = x;
ChangeCount[x] = diskreq->io_Actual;
CloseDevice(diskreq);
goto Out;
};
CloseDevice(diskreq);
};
Out:;
return(RetVal);
}
/********************************/
CheckBlock()
{
int Sum, Bootable, Virus; /* Virus is a flag, Bootable is a flag, Sum the cksum. */
int a, Unit;
int SCA; /* don't get scared, it's just a flag. */
Unit = WhoChanged();
CheckAgainYouFool:; /* oh oh, a label. Could be a goto later on! */
DisksChecked++;
SCA = FALSE;
/* Unit # to open is returned by "WhoChanged()" up above. */
if (Unit == -1) return;
error = OpenDevice("trackdisk.device",Unit,diskreq,0);
if (error > 0) return;
/* I've heard stories that pulling a read request to block zero with a
length of 1024 will cause the virus to write itself back. Not taking
any chances. */
diskreq->io_Command = CMD_READ;
diskreq->io_Data = diskbuffer;
diskreq->io_Length = 3*512;
diskreq->io_Offset = 0;
DoIO(diskreq);
diskreq->io_Length = 0;
diskreq->io_Command = TD_MOTOR;
DoIO(diskreq); /* turn off motor */
if (diskreq->io_Error > 19) return; /* disk error, lemme out */
CloseDevice(diskreq);
Sum = 0;
for (a=0; a<1024; a=a+4)
{
LastSum = Sum;
Sum = Sum + diskbuffer[a+3];
Sum = Sum + (diskbuffer[a+2] * 256);
Sum = Sum + (diskbuffer[a+1] * 65536);
Sum = Sum + (diskbuffer[a] * (65536 * 256));
if (LastSum > Sum) Sum++; /* took me a while to figger this out */
}
if (Sum != 0) return; /* if it's not bootable, we DONT want it! */
/* check specifically for SCA virus */
if (diskbuffer[8] == 'C')
if (diskbuffer[9] == 'H')
if (diskbuffer[10] == 'W')
{
SCA = TRUE; /* CHW is part of SCA virus */
SCAFound++;
};
/* compare boot block with real boot block. If it's not, notify God. */
Virus = FALSE;
for (x = 0; x < 39; x++) /* nuum of lements in bootblock */
{
if (diskbuffer[8+x] != bootblock[8+x])
{
Virus = TRUE;
};
};
/* Oh no, a Virus! */
if (Virus == TRUE)
{
/* Oh no, it's the SCA Virus! */
if (SCA != TRUE)
{
Delay(1);
NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
error = AutoRequest(LittleWindow, &Body1, &Pos, &Neg, 0, 0, 320, 75);
if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
Delay(1);
}
else
{
/* Phew, just a nonstandard boot block, probably */
Delay(1);
TEXTPTR[23] = '0'+Unit;
error = AutoRequest(LittleWindow, &SCABody, &SCAPos, &SCANeg, 0, 0, 320, 75);
if (error == TRUE) DoInstall(Unit); /* user wants it fixed. */
Delay(1);
};
};
Unit = WhoChanged(); /* more than one disk was changed. check again */
if (Unit != -1) goto CheckAgainYouFool;
}
/********************************/
/* This is where the boot code gets changed */
/********************************/
DoInstall(un)
int un; /* unit to write to */
{
register int x;
register int Sum;
int err, a;
/* Rewrite disk? Really? */
error = AutoRequest(LittleWindow, &REWBody, &REWPos, &REWNeg, 0, 0, 320, 75);
if (error != TRUE) return; /* user changed his brain. */
DisksInstalled++;
for (x = 0; x < 1024; x++)
diskbuffer[x] = 0; /* clear diskbuffer to zero. clean. */
for (x = 0; x < 50; x++)
{
diskbuffer[x] = bootblock[x]; /* copy boot code into buffer */
};
/* Write it ! */
error = OpenDevice("trackdisk.device", un,diskreq,0);
if (error > 0) return;
diskreq->io_Command = CMD_READ;
diskreq->io_Data = diskbuffer;
diskreq->io_Length = 512;
diskreq->io_Offset = 44*512;
DoIO(diskreq);
trygain: /* GOTO! A GOTO! OH NOOOO! */
diskreq->io_Command = TD_PROTSTATUS;
DoIO(diskreq); /* check if disk is write protected */
if (diskreq->io_Actual != 0)
{
error = AutoRequest(LittleWindow, &ERRBody, &ERRPos, &ERRNeg, 0, 0, 320, 75);
if (error == TRUE) /* error is true or false, depending on user */
{
goto trygain;
};
CloseDevice(diskreq);
return; /* unrecoverable write protect error!!!!!!!!! */
};
diskreq->io_Length = 1024; /* here we go! */
diskreq->io_Data = &diskbuffer[0];
diskreq->io_Command = CMD_WRITE;
diskreq->io_Offset = 0L;
DoIO(diskreq);
diskreq->io_Command = CMD_UPDATE; /* flush buffer to disk */
DoIO(diskreq);
error = diskreq->io_Error;
diskreq->io_Length = 0;
diskreq->io_Command = ETD_MOTOR;
DoIO(diskreq); /* turn off motor */
CloseDevice(diskreq);
if (error > 19)
{
SetWindowTitles(LittleWindow, "Error, Nothing Done.", -1);
}
else
{
SetWindowTitles(LittleWindow, "Disk Healed.", -1);
};
Delay(100);
SetWindowTitles(LittleWindow, TITLETEXT, -1);
}
/************************/